home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-08-29 | 27.3 KB | 1,230 lines | [TEXT/MMCC] |
- // slide show-specific procedures
-
-
- #include "Prototypes.h"
- #include "QDOffscreen.h"
- #include "ImageFileFormats.h"
- #include "Palettes.h"
- #include "PictUtils.h"
- #include "DialogUtils.h"
- #include "ScrollDialog.h"
- #include "ShowHideMenubar.h"
- #include "fade.h"
- #include <Aliases.h>
-
- long gSlideTicks;
- long gLastTicks;
- short gSlideIndex;
- short gSlideMaxIndex;
- short gSlidePhase;
- short gMonitorDepth = 8;
- FSSpec gSlideFile;
- GWorldPtr gSlideImage = NULL;
- Boolean gRepeat = FALSE;
- Boolean gTransitions = FALSE;
- Boolean gUsePalManager = FALSE;
- Boolean gDisplayRandom = FALSE;
- Boolean gShowNames = FALSE;
- Boolean gScaleImages = FALSE;
- Boolean gHideMBar = FALSE;
- Boolean gAtLeastOneOpened;
- Boolean gAutoRun;
- Boolean gIsFaded = FALSE;
- OSType gFType;
- long gDirectory = 0;
- CTabHandle gCLUT = NULL;
-
- unsigned long* gSlideList = NULL; // used for random order display
-
- extern FSSpec gSlideFolder;
- extern Boolean gFolderChosen;
- extern WindowPtr gSlideWindow;
- extern MenuHandle gFileMenu;
-
- enum
- {
- kSlideStopped,
- kSlideRunning,
- kSlidePaused,
- kSlideError
- };
-
-
- static void InstallDitherProc(GrafPtr theOSPort);
- static pascal void DitherBitsProc(BitMap *srcBits,Rect *srcRect,
- Rect *destRect,int mode,RgnHandle maskRgn);
- static void RemoveDitherProc(GrafPtr theOSPort);
-
-
-
- void StartSlideshow()
- {
- GDHandle mainDevice;
-
- if (gFolderChosen)
- {
- if (gSlidePhase == kSlideStopped)
- {
- gSlideIndex = 0;
- gAtLeastOneOpened = FALSE;
-
- // find out how many slides to show. This is the number of files in the
- // folder. This also sets up the target folder.
-
- gSlideMaxIndex = FSpCountFiles(&gSlideFolder);
-
- // find out the monitor depth so that we can optimise palettes, etc.
-
- mainDevice = GetMainDevice();
- gMonitorDepth = (*(*mainDevice)->gdPMap)->pixelSize;
-
- if (! gUsePalManager && (gMonitorDepth < 16))
- RestoreDeviceClut(NULL);
-
- // make sure first slide gets show immediately
-
- gLastTicks = TickCount() - gSlideTicks;
-
- if (gDisplayRandom)
- SetUpRandomList();
- }
-
- if (gSlideMaxIndex > 0)
- {
- if (gHideMBar)
- SetMBarState(HIDE);
-
- gSlidePhase = kSlideRunning;
-
- DisableItem(gFileMenu,kItemChooseSlides);
- DisableItem(gFileMenu,kItemGo);
- EnableItem(gFileMenu,kItemStop);
- EnableItem(gFileMenu,kItemStartOver);
- }
- }
- }
-
-
-
- void RunSlideshow()
- {
- long curTicks;
- OSErr theErr;
-
- if (gSlidePhase == kSlideRunning && gFolderChosen)
- {
- curTicks = TickCount();
-
- if (curTicks >= (gSlideTicks + gLastTicks))
- {
- // time for the next slide!
-
- gSlideIndex++;
-
- if (gSlideIndex > gSlideMaxIndex)
- {
- if (! gAtLeastOneOpened)
- {
- // if we have circled completely but nowt was opened,
- // tell the user that there is nothing in the folder
-
- (void) Alert(130,NULL);
- gSlidePhase = kSlideError;
- StopSlideshow();
- return;
- }
-
- if (gRepeat)
- gSlideIndex = 1; // otherwise repeat from first slide
- else
- {
- (void) Alert(129,NULL);
- gSlidePhase = kSlideError;
- StopSlideshow();
- return;
- }
- }
-
- gFType = 0;
-
- // if here, the slide show is to continue, so set up the next file.
-
- SetUpNextSlideFile();
-
- // if gFType is not zero, then open and display the file. If it IS zero it
- // means that the file indexed is one we cannot open. If we end up circling around
- // completely, we should show a message that the folder doesn't contain any openable
- // images.
-
- if (gSlidePhase == kSlideRunning && gFType)
- {
- gLastTicks = curTicks;
- gAtLeastOneOpened = TRUE;
- OpenNextFile();
- }
- }
- }
- }
-
-
-
- void StopSlideshow()
- {
- if (gSlidePhase == kSlideRunning)
- gSlidePhase = kSlidePaused;
- else
- gSlidePhase = kSlideStopped;
-
- SetMBarState(SHOW);
-
- if (gTransitions && gIsFaded)
- {
- fade_to_black(16,fadeMainOnly,FALSE);
- gIsFaded = FALSE;
- }
- EnableItem(gFileMenu,kItemChooseSlides);
- EnableItem(gFileMenu,kItemGo);
- DisableItem(gFileMenu,kItemStop);
- EnableItem(gFileMenu,kItemStartOver);
- }
-
-
- void ResetSlideshow()
- {
- if (gSlidePhase == kSlidePaused)
- gSlidePhase = kSlideStopped;
- gSlideIndex = 0;
- StartSlideshow();
- }
-
-
-
- short FSpCountFiles(FSSpec* aFolderSpec)
- {
- // returns the number of files in the given folder. If the filespec is not a folder,
- // this returns zero. This does not take into account the type of the files.
-
- CInfoPBRec cb;
- OSErr theErr;
- short count = 0;
- Str255 parentName;
-
- // search the parent directory
-
- CopyPString(aFolderSpec->name,parentName);
- cb.dirInfo.ioCompletion = NULL;
- cb.dirInfo.ioNamePtr = parentName;
- cb.dirInfo.ioVRefNum = aFolderSpec->vRefNum;
- cb.dirInfo.ioFDirIndex = 0;
- cb.dirInfo.ioDrDirID = aFolderSpec->parID; // search the parent for this one
-
- theErr = PBGetCatInfo(&cb,FALSE);
-
- if (theErr == noErr && cb.dirInfo.ioFlAttrib & 16)
- {
- // OK, we found the desired directory here. That was done to obtain the
- // "HARD" directory ID of the folder we want to use.
-
- gDirectory = cb.dirInfo.ioDrDirID;
- count = cb.dirInfo.ioDrNmFls;
- }
- else
- gDirectory = 0;
-
- return count;
- }
-
-
- void SetUpNextSlideFile()
- {
- // prepares the next slide for display. This gets the next indexed file in the directory,
- // and sets the gSlideFile variable to it's FSSpec. it also sets gFType to the file's type.
-
- CInfoPBRec cb;
- OSErr theErr;
-
- if (gFolderChosen && gDirectory != 0)
- {
- cb.hFileInfo.ioNamePtr = gSlideFile.name;
- cb.hFileInfo.ioVRefNum = gSlideFile.vRefNum = gSlideFolder.vRefNum;
- if (gDisplayRandom && gSlideList)
- cb.hFileInfo.ioFDirIndex = HiWord(gSlideList[gSlideIndex - 1]);
- else
- cb.hFileInfo.ioFDirIndex = gSlideIndex;
- cb.hFileInfo.ioDirID = gSlideFile.parID = gDirectory;
-
- theErr = PBGetCatInfo(&cb,FALSE);
-
- if (theErr == noErr)
- {
- // make sure the file spec is correct, and get the file type
-
- if (! (cb.hFileInfo.ioFlAttrib & 16))
- {
- gFType = cb.hFileInfo.ioFlFndrInfo.fdType;
-
- // is it one we can open?
-
- if (gFType == 'TEXT')
- {
- // see if this is really a GIF file- if it is we can open
- // it after all. This is common with ISO 9660 CD-ROMs
-
- short refNum;
- OSErr fErr;
- long byteCount;
- long sigBytes;
-
- fErr = FSpOpenDF(&gSlideFile,fsCurPerm,&refNum);
- if (fErr == noErr)
- {
- byteCount = sizeof(long);
-
- fErr = FSRead(refNum,&byteCount,&sigBytes);
-
- if (sigBytes == 'GIF8')
- gFType = 'GIFf';
-
- fErr = FSClose(refNum);
- }
- }
-
- if (gFType == 'PICT' ||
- gFType == 'TIFF' ||
- gFType == 'JPEG' ||
- gFType == 'JFIF' ||
- gFType == 'GIFf')
- return;
- }
- }
- }
- gFType = 0;
- }
-
-
-
- void OpenNextFile()
- {
- PicHandle tempPic = NULL;
- short refNum = -1;
- OSErr theErr;
-
- ObscureCursor();
- theErr = FSpOpenDF(&gSlideFile,fsCurPerm,&refNum);
-
- if (theErr == noErr)
- {
- switch (gFType)
- {
- case 'PICT':
- tempPic = OpenPICT(refNum);
- break;
- case 'JPEG':
- case 'JFIF':
- tempPic = OpenJPEG(refNum);
- break;
- case 'GIFf':
- FSClose(refNum);
- tempPic = OpenGIF(refNum);
- refNum = -1;
- break;
- case 'TIFF':
- FSClose(refNum);
- tempPic = OpenTIFF(refNum);
- refNum = -1;
- break;
- default:
- tempPic = NULL;
- break;
- }
- if (refNum != -1)
- FSClose(refNum);
-
- if (tempPic)
- {
- if (GetHandleSize((Handle) tempPic) != sizeof(Picture))
- DisplayPicture(tempPic);
- else
- SysBeep(1);
- KillPicture(tempPic);
- }
- else
- SysBeep(1); // an error occurred
- }
- }
-
- #define kPICTHeaderSize 512
-
- PicHandle OpenPICT(short refNum)
- {
- long pSize;
- Handle pH;
- OSErr theErr;
-
- theErr = GetEOF(refNum,&pSize);
-
- pSize -= kPICTHeaderSize;
-
- pH = NewHandle(pSize);
-
- if (pH)
- {
- SetFPos(refNum,fsFromStart,kPICTHeaderSize);
-
- theErr = FSRead(refNum,&pSize,*pH);
-
- if (theErr)
- {
- DisposeHandle(pH);
- pH = NULL;
- }
- }
- return (PicHandle) pH;
- }
-
- PicHandle OpenJPEG(short refNum)
- {
- OSErr theErr;
- PicHandle pH;
-
- theErr = ConvertFromJFIF(gSlideFile.name,refNum,&pH);
-
- if (theErr)
- return NULL;
- else
- return pH;
- }
-
- PicHandle OpenTIFF(short refNum)
- {
- PicHandle pH = NULL;
- OSErr theErr;
-
- theErr = ConvertTIFFToPICT(&gSlideFile,&pH);
- if (theErr)
- return NULL;
- else
- return pH;
- }
-
- PicHandle OpenGIF(short refNum)
- {
- PicHandle pH = NULL;
- OSErr theErr;
-
- theErr = ConvertGIFtoPICT(&gSlideFile,&pH);
- if (theErr)
- return NULL;
- else
- return pH;
- }
-
-
- const RGBColor BLACK = {0,0,0};
- const RGBColor WHITE = {0xFFFF,0xFFFF,0xFFFF};
-
-
- void DisplayPicture(PicHandle thePic)
- {
- // prepares the GWorld. This function always uses the screen depth for its port and dithers
- // when creating it, never when showing it.
-
- Rect frame;
- OSErr theErr;
- CTabHandle pCT = NULL;
- short picDepth;
- PictInfo pi;
- Boolean usingColourReduction = FALSE;
- GWorldPtr tempWorld = NULL;
- PixMapHandle tPix;
-
- if (gSlideImage)
- DisposeGWorld(gSlideImage);
-
- gSlideImage = NULL;
- frame = (*thePic)->picFrame;
- OffsetRect(&frame,-frame.left,-frame.top);
-
- // the colour table for the image depends on what characteristics the target screen has.
- // If indexed, we need to obtain an optimal palette if that's what the user wants. For
- // 16 colour screens, we never try to optimise the palette (too few colours to make it
- // worthwhile), so only 8-bit screens are considered for this.
-
- if ((gMonitorDepth == 8) && gUsePalManager)
- {
- theErr = GetPictureInfo(thePic,&gPicInfo);
- picDepth = gPicInfo.picDepth;
-
- // if the pic depth is greater than 8, we need to do a colour reduction to obtain a
- // good colour table. If less, we use the default colour table, and if equal, we use
- // its own colour table.
-
- switch (picDepth)
- {
- case 16:
- case 32:
- // the image is direct. To get the best results with JPEG compressed pictures,
- // it is necessary to image the picture into a temporary GWorld and sample
- // the colours from its pixmap, because the picture utilities do not do a
- // good job on such pictures. This is tedious and memory hungry, but what can
- // you do?
-
- theErr = NewGWorld(&tempWorld,picDepth,&frame,NULL,NULL,0);
-
- if (theErr == noErr)
- {
- GDHandle saveDevice;
- CGrafPtr savePort;
-
- GetGWorld(&savePort,&saveDevice);
- SetGWorld(tempWorld,NULL);
-
- ForeColor(blackColor);
- BackColor(whiteColor);
-
- tPix = GetGWorldPixMap(tempWorld);
-
- if (LockPixels(tPix))
- {
- EraseRect(&frame);
- DrawPicture(thePic,&frame);
-
- theErr = GetPixMapInfo( tPix,
- &pi,
- returnColorTable + suppressBlackAndWhite,
- 254,
- medianMethod,
- 0 );
- UnlockPixels(tPix);
- }
-
- SetGWorld(savePort,saveDevice);
- }
-
- if (theErr == noErr)
- {
- short i;
-
- pCT = pi.theColorTable;
-
- // this table has 254 colours, but no B & W, so we extend it by two entries
- // and add in the B & W entries.
-
- SetHandleSize((Handle) pCT,GetHandleSize((Handle) pCT) + (sizeof(ColorSpec) * 2));
-
- for (i = 253;i >= 0;i--)
- {
- (*pCT)->ctTable[i + 1].rgb = (*pCT)->ctTable[i].rgb;
- (*pCT)->ctTable[i + 1].value = i + 1;
- }
- (*pCT)->ctTable[0].rgb = WHITE;
- (*pCT)->ctTable[0].value = 0;
- (*pCT)->ctTable[255].rgb = BLACK;
- (*pCT)->ctTable[255].value = 255;
- usingColourReduction = TRUE;
- }
- break;
- case 8:
- pCT = gPicInfo.picColours;
- break;
- default:
- break;
- }
- }
- else
- {
- if (gMonitorDepth < 16)
- {
- GDHandle mS = GetMainDevice();
-
- pCT = (*(*mS)->gdPMap)->pmTable;
- HandToHand((Handle*) &pCT);
- }
- }
-
- // create the GWorld with the monitor's depth, and the colour table we have established.
-
- theErr = NewGWorld(&gSlideImage,gMonitorDepth,&frame,pCT,NULL,0);
-
- if (theErr == noErr)
- {
- GDHandle saveDevice;
- CGrafPtr savePort;
- PixMapHandle ppix;
-
- GetGWorld(&savePort,&saveDevice);
- SetGWorld(gSlideImage,NULL);
-
- ForeColor(blackColor);
- BackColor(whiteColor);
-
- ppix = GetGWorldPixMap(gSlideImage);
-
- if (LockPixels(ppix))
- {
- if (usingColourReduction && tempWorld)
- {
- LockPixels(tPix);
- CopyBits((BitMap*) *tPix,(BitMap*) *ppix,&frame,&frame,ditherCopy,NULL);
- UnlockPixels(tPix);
- }
- else
- {
- if (gMonitorDepth < picDepth)
- InstallDitherProc((GrafPtr) gSlideImage);
-
- EraseRect(&frame);
- DrawPicture(thePic,&frame);
-
- if (gMonitorDepth < picDepth)
- RemoveDitherProc((GrafPtr) gSlideImage);
- }
- UnlockPixels(ppix);
- }
- SetGWorld(savePort,saveDevice);
-
- if (tempWorld)
- DisposeGWorld(tempWorld);
-
- if (pCT)
- DisposeCTable(pCT);
-
-
- // if we are fading the screen, do it here.
-
- if (gTransitions)
- {
- fade_to_black(16,fadeMainOnly,TRUE);
- gIsFaded = TRUE;
- }
- SetPort(gSlideWindow);
- SelectWindow(gSlideWindow);
-
- ForeColor(blackColor);
- PaintRect(&gSlideWindow->portRect);
-
- // refresh the window
-
- InvalRect(&gSlideWindow->portRect);
- }
- }
-
- /*
- void DisplayPictureOldWay(PicHandle thePic)
- {
- // prepares the picture for drawing. This sets up the global GWorld to the size, depth,
- // colour, etc of the picture, and draws it to the GWorld. It then forces an update of the
- // display window which presents the image to the viewer, overwriting the old one. This
- // function also creates a palette for the window with optimal colours.
-
- OSErr theErr;
- Rect frame;
- PictInfo pi;
- short nColours = 0,picDepth;
- CTabHandle pCT;
-
- if (gSlideImage)
- DisposeGWorld(gSlideImage);
-
- gSlideImage = NULL;
-
- // get the colour information for the picture
-
- if (gMonitorDepth > 4)
- {
- theErr = GetPictureInfo(thePic,&gPicInfo);
-
- if ((theErr == noErr) && gPicInfo.infoValid)
- {
- pCT = gPicInfo.picColours;
- frame = gPicInfo.picSize;
- picDepth = gPicInfo.picDepth;
-
- theErr = NewGWorld(&gSlideImage,picDepth,&frame,pCT,NULL,0);
- }
- }
- else
- {
- // for 16-colour images, we use a different strategy. The GWorld is built using
- // the SCREEN parameters, and the image is dithered into it by installing a
- // ditherProc. This gives the best results on 16-colour screens and is faster.
- // Since the poor old LC with 16 grays is a definite target machine, this
- // "optimisation" is done to help it along.
-
- GDHandle mainScreen;
-
- mainScreen = GetMainDevice();
-
- pCT = (*(*mainScreen)->gdPMap)->pmTable;
- frame = (*thePic)->picFrame;
- OffsetRect(&frame,-frame.left,-frame.top);
- picDepth = 8;
-
- theErr = NewGWorld(&gSlideImage,gMonitorDepth,&frame,pCT,NULL,0);
-
- pCT = NULL;
- }
-
-
- if (theErr == noErr)
- {
- PixMapHandle ppix;
- CGrafPtr savePort;
- GDHandle saveDevice;
-
- GetGWorld(&savePort,&saveDevice);
- SetGWorld(gSlideImage,NULL);
-
- // install a ditherProc into the GWorld port to ensure that DrawPicture gets
- // dithered correctly. (16 colours or less only.)
-
- if (gMonitorDepth < 8)
- InstallDitherProc((GrafPtr) gSlideImage);
-
- ForeColor(blackColor);
- BackColor(whiteColor);
-
- if (LockPixels(ppix = GetGWorldPixMap(gSlideImage)))
- {
- EraseRect(&frame); // in case image has transparent parts
- DrawPicture(thePic,&frame); // may take a while if using embedded compression
- UnlockPixels(ppix);
- }
- SetGWorld(savePort,saveDevice);
-
- if (gMonitorDepth < 8)
- RemoveDitherProc((GrafPtr) gSlideImage);
-
- if (gTransitions)
- {
- fade_to_black(16,fadeMainOnly,TRUE);
- gIsFaded = TRUE;
- }
- SetPort(gSlideWindow);
- SelectWindow(gSlideWindow);
-
- ForeColor(blackColor);
- PaintRect(&gSlideWindow->portRect);
-
- // Set up a display palette. We pursue a number of strategies: If the monitor is not
- // indexed, don't bother at all. If the monitor has 256 colours, and the image is also
- // 256 colours, use the image's colour table to make a palette. Otherwise use the
- // system colour reduction utility. For 16 colours, the GWorld is matched to the screen.
- // The user can switch of this facility altogether, which affects the gUsePalManager
- // flag.
-
- if (gUsePalManager && (gMonitorDepth == 8))
- {
- if (pCT)
- {
- pi.thePalette = NewPalette(256,pCT,pmTolerant,0);
- theErr = noErr;
- }
- else
- theErr = GetPixMapInfo(ppix,&pi,returnPalette + suppressBlackAndWhite,254,systemMethod,0);
-
- if (theErr == noErr)
- {
- NSetPalette(gSlideWindow,pi.thePalette,pmAllUpdates);
- DisposePalette(pi.thePalette);
- }
- }
- }
- else
- SysBeep(1);
-
- if (pCT)
- DisposeCTable(pCT);
-
- SetPort(gSlideWindow);
- ActivatePalette(gSlideWindow);
- InvalRect(&gSlideWindow->portRect);
- }
- */
-
-
- void CentreRects(Rect *r1,Rect *r2)
- {
- /* Offsets the coordinates of r2 so that it is centred with respect to r1. r1 is not
- changed. Rectangles can be different sizes or same size */
-
- short dH,dV;
-
- dH = ((r1->right - r1->left) - (r2->right - r2->left))/2 - r2->left + r1->left;
- dV = ((r1->bottom - r1->top) - (r2->bottom - r2->top))/2 - r2->top + r1->top;
- OffsetRect(r2,dH,dV);
- }
-
-
-
- void DrawTheWindow(WindowPtr theWindow)
- {
- // this function draws the contents of the window. This is called from an update event.
-
- Rect r,sr,pr;
- PixMapHandle ppix;
- RGBColor saveBack;
- Str15 numStr;
- Str255 nameStr;
-
- if (gSlideImage)
- {
- if ((gMonitorDepth == 8) && gUsePalManager)
- {
- PaletteHandle pH;
- CTabHandle pCT;
-
- ppix = GetGWorldPixMap(gSlideImage);
- pCT = (*ppix)->pmTable;
-
- pH = NewPalette(256,pCT,pmTolerant + pmExplicit,0);
- NSetPalette(gSlideWindow,pH,pmNoUpdates);
-
- DisposePalette(pH);
- }
-
- if (gTransitions && gIsFaded)
- fade_to_black(1,fadeMainOnly,TRUE);
-
- r = sr = gSlideImage->portRect;
- pr = theWindow->portRect;
-
- if (gScaleImages)
- Scale2Rects(&r,&pr);
- else
- CentreRects(&pr,&r);
-
- GetBackColor(&saveBack);
- ForeColor(blackColor);
- BackColor(whiteColor);
-
- if (LockPixels(ppix = GetGWorldPixMap(gSlideImage)))
- {
- short mode;
-
- mode = gScaleImages? ditherCopy : srcCopy;
-
- CopyBits((BitMap*) *ppix,&theWindow->portBits,&sr,&r,mode,NULL);
- UnlockPixels(ppix);
- }
-
- if (gShowNames)
- {
- short remaining;
-
- CopyPString(gSlideFile.name,nameStr);
- ConcatPStrings(nameStr,"\p (Slide ");
- if (gDisplayRandom && gSlideList)
- NumToString(HiWord(gSlideList[gSlideIndex - 1]),numStr);
- else
- NumToString(gSlideIndex,numStr);
- ConcatPStrings(nameStr,numStr);
- ConcatPStrings(nameStr,"\p of ");
- NumToString(gSlideMaxIndex,numStr);
- ConcatPStrings(nameStr,numStr);
- if (gDisplayRandom && ! gRepeat)
- {
- remaining = gSlideMaxIndex - gSlideIndex;
-
- if (remaining > 0)
- {
- ConcatPStrings(nameStr,"\p, ");
- NumToString(remaining,numStr);
- ConcatPStrings(nameStr,numStr);
- ConcatPStrings(nameStr,"\p left to show.");
- }
- }
- ConcatPStrings(nameStr,"\p)");
-
- sr = pr;
- sr.top = r.bottom + 8;
- sr.bottom = sr.top + 20;
-
- ForeColor(whiteColor);
- BackColor(blackColor);
-
- TextFont(geneva);
- TextSize(9);
- TextFace(bold);
- TextBox(&nameStr[1],nameStr[0],&sr,teJustCenter);
- ForeColor(blackColor);
- }
-
- if (gTransitions && gIsFaded && (gMonitorDepth < 16))
- {
- fade_to_black(16,fadeMainOnly,FALSE);
- gIsFaded = FALSE;
- }
- RGBBackColor(&saveBack);
- }
- }
-
-
- #define kOptionsDialogID 1000
-
- enum
- {
- kOpItemDelay = 3,
- kOpItemRepeat = 6,
- kOpItemPalette,
- kOpItemNames,
- kOpItemScale,
- kOpItemLine = 11,
- kOpItemHideMBar,
- kOpItemTransition = 14,
- kOpItemRandom
- };
-
- Boolean DoOptionsDialog()
- {
- // handles the settings. Since this affects globals only (this is a quick & dirty app,
- // remeber) the result can be ignored.
-
- DialogPtr theDialog;
- short item,itemType;
- Handle itemHand;
- Rect itemBox;
- Boolean result = FALSE;
- long val;
- Str255 tempStr;
-
- theDialog = GetNewDialog(kOptionsDialogID,NULL,(WindowPtr) - 1L);
-
- if (theDialog)
- {
- StdDialogSetup(theDialog);
- SetItemValue(theDialog,kOpItemRepeat,gRepeat);
- SetItemValue(theDialog,kOpItemPalette,gUsePalManager);
- SetItemValue(theDialog,kOpItemRandom,gDisplayRandom);
- SetItemValue(theDialog,kOpItemTransition,gTransitions);
- SetItemValue(theDialog,kOpItemNames,gShowNames);
- SetItemValue(theDialog,kOpItemScale,gScaleImages);
- SetItemValue(theDialog,kOpItemHideMBar,gHideMBar);
- SetUniversalUserItem(theDialog,kOpItemLine,(ProcPtr) FrameRectUserItem);
- SetUniversalUserItem(theDialog,13,(ProcPtr) EditFieldDecorator);
-
- GetDItem(theDialog,kOpItemDelay,&itemType,&itemHand,&itemBox);
- val = gSlideTicks / 60;
- NumToString(val,tempStr);
- SetIText(itemHand,tempStr);
- SelIText(theDialog,kOpItemDelay,0,32767);
-
- ShowWindow(theDialog);
- OutlineDialogItem(theDialog,ok);
-
- item = 0;
-
- while(item == 0)
- {
- ModalDialog(NULL,&item);
-
- switch (item)
- {
- case ok:
- gRepeat = GetItemValue(theDialog,kOpItemRepeat);
- gTransitions = GetItemValue(theDialog,kOpItemTransition);
- gShowNames = GetItemValue(theDialog,kOpItemNames);
- gScaleImages = GetItemValue(theDialog,kOpItemScale);
- gHideMBar = GetItemValue(theDialog,kOpItemHideMBar);
- gDisplayRandom = GetItemValue(theDialog,kOpItemRandom);
- gUsePalManager = GetItemValue(theDialog,kOpItemPalette);
-
- GetDItem(theDialog,kOpItemDelay,&itemType,&itemHand,&itemBox);
- GetIText(itemHand,tempStr);
- StringToNum(tempStr,&val);
- gSlideTicks = val * 60;
- result = TRUE;
- case cancel:
- break;
- default:
- GetDItem(theDialog,item,&itemType,&itemHand,&itemBox);
-
- if ((itemType & 0x7F) == ctrlItem + chkCtrl)
- SetCtlValue((ControlHandle) itemHand,GetCtlValue((ControlHandle) itemHand) ^ 1);
- item = 0;
- break;
- }
- }
- DisposeUserItem(theDialog,kOpItemLine);
- DisposeUserItem(theDialog,13);
- DisposeDialog(theDialog);
- }
- return result;
- }
-
-
- typedef struct
- {
- Boolean repeatFlag;
- Boolean transitFlag;
- Boolean namesFlag;
- Boolean scaleFlag;
- Boolean folderValid;
- Boolean hideMBar;
- Boolean autoRun;
- Boolean usePalManager;
- Boolean randomOrder;
- Boolean spare1;
- Boolean spare2;
- Boolean spare3;
- long tticks;
- }
- slidePrefs, *slidePrefPtr, **slidePrefHdl;
-
- #define kSlidePrefResType 'SLID'
- #define kSlidePrefResID 128
-
-
- void SavePrefs()
- {
- // this saves the current settings and target folder in its OWN RESOURCES. Though not
- // recommended really, this is done to make it easy to create stand-alone slideshows on
- // a disk - the user can simply double-click and away it goes. If the folder is not found,
- // the slide show will stop.
-
- slidePrefHdl spH;
- Boolean isResource = TRUE;
- AliasHandle folderAlias;
- OSErr theErr;
-
- spH = (slidePrefHdl) GetResource(kSlidePrefResType,kSlidePrefResID);
-
- if (spH == NULL)
- {
- spH = (slidePrefHdl) NewHandleClear(sizeof(slidePrefs));
- isResource = FALSE;
- }
- if (spH)
- {
- (*spH)->repeatFlag = gRepeat;
- (*spH)->transitFlag = gTransitions;
- (*spH)->namesFlag = gShowNames;
- (*spH)->scaleFlag = gScaleImages;
- (*spH)->hideMBar = gHideMBar;
- (*spH)->autoRun = (gSlidePhase == kSlideRunning);
- (*spH)->usePalManager = gUsePalManager;
- (*spH)->randomOrder = gDisplayRandom;
- (*spH)->tticks = gSlideTicks;
-
- (*spH)->folderValid = gFolderChosen;
- }
-
- if (isResource)
- ChangedResource((Handle) spH);
- else
- AddResource((Handle) spH,kSlidePrefResType,kSlidePrefResID,"\p");
-
- if (! ResError())
- {
- WriteResource((Handle) spH);
- ReleaseResource((Handle) spH);
- }
-
- // we now save the folder spec as an alias record, which works across volumes-
- // necessary if you want to make a slideshow on a floppy disk that runs automatically
- // on any machine it is inserted into.
-
- folderAlias = (AliasHandle) GetResource('alis',128);
-
- if (folderAlias)
- {
- RmveResource((Handle) folderAlias);
- DisposeHandle((Handle) folderAlias);
- }
-
- theErr = NewAlias(NULL,&gSlideFolder,&folderAlias);
-
- if (theErr == noErr)
- {
- AddResource((Handle) folderAlias,'alis',128,"\p");
- WriteResource((Handle) folderAlias);
- ReleaseResource((Handle) folderAlias);
- }
- }
-
-
- void RestorePrefs()
- {
- // this recovers the settings from the resources.
-
- slidePrefHdl spH;
- AliasHandle folderAlias;
- OSErr theErr;
- Boolean wasChanged;
-
- spH = (slidePrefHdl) GetResource(kSlidePrefResType,kSlidePrefResID);
-
- if (spH)
- {
- gRepeat = (*spH)->repeatFlag;
- gTransitions = (*spH)->transitFlag;
- gShowNames = (*spH)->namesFlag;
- gScaleImages = (*spH)->scaleFlag;
- gHideMBar = (*spH)->hideMBar;
- gSlideTicks = (*spH)->tticks;
-
- gFolderChosen = (*spH)->folderValid;
- gAutoRun = (*spH)->autoRun;
- gDisplayRandom = (*spH)->randomOrder;
- gUsePalManager = (*spH)->usePalManager;
-
- ReleaseResource((Handle) spH);
- }
-
- // fetch the folder spec
-
- folderAlias = (AliasHandle) GetResource('alis',128);
-
- if (folderAlias)
- {
- theErr = ResolveAlias(NULL,folderAlias,&gSlideFolder,&wasChanged);
-
- ReleaseResource((Handle) folderAlias);
-
- if (theErr)
- gFolderChosen = FALSE;
- }
- }
-
-
- void DoAboutBox()
- {
- // shows the enhanced about box which contains the scrollable help text, etc.
-
- short aHit = ScrollTextDialog(1001,2,128);
- }
-
-
- void SetSlideWindowSize(WindowPtr theWindow)
- {
- Rect bounds;
-
- bounds = qd.screenBits.bounds;
- if (! gHideMBar)
- bounds.top += GetMBarHeight();
-
- SizeWindow(theWindow,bounds.right - bounds.left,bounds.bottom - bounds.top,TRUE);
- MoveWindow(theWindow,bounds.left,bounds.top,FALSE);
- }
-
-
- void DoOptions()
- {
- if (DoOptionsDialog())
- {
- if (gHideMBar && gSlidePhase == kSlideRunning)
- SetMBarState(HIDE);
- else
- SetMBarState(SHOW);
-
- SetPort(gSlideWindow);
- SetSlideWindowSize(gSlideWindow);
- PaintRect(&gSlideWindow->portRect);
- InvalRect(&gSlideWindow->portRect);
- }
- }
-
-
- void InstallDitherProc(GrafPtr theOSPort)
- {
- /* sets up a bottleneck procedure for DrawPicture to dither pictures drawn into the
- port. This is useful when drawing deep pictures into shallow ports */
-
- CQDProcsPtr osProcs;
- Boolean pIsColour;
- QDBitsUPP ditherProcUPP;
-
- if (theOSPort)
- {
- pIsColour = ((theOSPort->portBits.rowBytes & 0xC000) != 0);
- if (pIsColour)
- {
- osProcs = (CQDProcsPtr) NewPtr(sizeof(CQDProcs));
- if (osProcs)
- {
- SetStdCProcs(osProcs);
-
- ditherProcUPP = NewQDBitsProc((ProcPtr) DitherBitsProc);
-
- osProcs->bitsProc = ditherProcUPP;
- theOSPort->grafProcs = (QDProcsPtr) osProcs;
- }
- }
- }
- }
-
-
-
- pascal void DitherBitsProc(BitMap *srcBits,Rect *srcRect,
- Rect *destRect,int mode,RgnHandle maskRgn)
- {
- /* special filter proc to dither pictures containing copybits opcodes */
-
- StdBits(srcBits,srcRect,destRect,mode | ditherCopy,maskRgn);
- }
-
-
- void RemoveDitherProc(GrafPtr theOSPort)
- {
- // dispose of the dither proc's routine descriptor
-
- CQDProcsPtr grafProcs;
- QDBitsUPP ditherProcUPP;
-
-
- grafProcs = (CQDProcsPtr) theOSPort->grafProcs;
-
- if (grafProcs)
- {
- ditherProcUPP = grafProcs->bitsProc;
- if (ditherProcUPP)
- DisposeRoutineDescriptor(ditherProcUPP);
-
- DisposePtr((Ptr) grafProcs);
- theOSPort->grafProcs = NULL;
- }
- }
-
-
- void SetUpRandomList()
- {
- // if we're displaying randomly, we create a random list. This consists of an array of
- // longs, with one value per slide. The HiWord is the slide index (1,2,3...n) and the
- // LoWord is a random number. Once done, we sort the list based on the random number
- // using a simple bubblesort. The file index is then picked at run time in array order.
- // This ensures that each slide gets shown once and only once even in Random order.
-
- short i,m,n,k;
- unsigned long temp;
-
- GetDateTime((unsigned long*) &qd.randSeed);
-
- if (gSlideList)
- DisposePtr((Ptr) gSlideList);
-
- gSlideList = (unsigned long*) NewPtrClear(sizeof(long) * gSlideMaxIndex);
-
- if (gSlideList)
- {
- for(i = 0;i < gSlideMaxIndex;i++)
- gSlideList[i] = ((unsigned long)(i + 1) << 16) | (unsigned short) Random();
-
- // now sort the list based on the LoWord
-
- m = gSlideMaxIndex - 1;
-
- for (n = m;n >= 0;n--)
- {
- for (i = 0;i < n;i++)
- {
- if (LoWord(gSlideList[i + 1]) < LoWord(gSlideList[i]))
- {
- temp = gSlideList[i];
- gSlideList[i] = gSlideList[i + 1];
- gSlideList[i + 1] = temp;
- }
- }
- }
- }
- }
-